import os
import uuid
from datetime import datetime
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy.orm import Session
from PIL import Image
import aiofiles

from database.connection import get_db
from database.models import User, UploadFile as UploadFileModel
from utils.auth import get_current_user_id

router = APIRouter(prefix="/upload", tags=["文件上传"])
security = HTTPBearer(auto_error=False)

# 上传配置
UPLOAD_DIR = "uploads"
AVATAR_DIR = os.path.join(UPLOAD_DIR, "avatars")
FILE_DIR = os.path.join(UPLOAD_DIR, "files")
MAX_FILE_SIZE = 30 * 1024 * 1024  # 10MB
MAX_AVATAR_SIZE = 5 * 1024 * 1024  # 5MB
# 图片类型配置
ALLOWED_IMAGE_TYPES = {"image/jpeg", "image/png", "image/gif", "image/webp"}

# 视频类型配置
ALLOWED_VIDEO_TYPES = {"video/mp4", "video/avi", "video/mov", "video/wmv"}

# 允许的文件类型配置
ALLOWED_FILE_TYPES = {
    # 图片类型
    "image/jpeg", "image/png", "image/gif", "image/webp",
    # 视频类型
    "video/mp4", "video/avi", "video/mov", "video/wmv",
    # 文档类型
    "application/pdf", "text/plain", "application/msword",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    "application/vnd.ms-excel",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
}

# 确保上传目录存在
os.makedirs(AVATAR_DIR, exist_ok=True)
os.makedirs(FILE_DIR, exist_ok=True)


def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security), db: Session = Depends(get_db)):
    """
    获取当前登录用户
    """
    user_id = get_current_user_id(credentials)
    user = db.query(User).filter(User.id == user_id, User.is_delete == False).first()
    if not user:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="用户不存在",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return user


def validate_file_size(file: UploadFile, max_size: int):
    """
    验证文件大小
    如果文件大小超过限制，抛出HTTPException
    """
    if file.size and file.size > max_size:
        raise HTTPException(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail=f"文件大小超过限制 ({max_size // (1024*1024)}MB)"
        )


def validate_file_type(file: UploadFile, allowed_types: set):
    """
    验证文件类型
    如果文件类型不被支持，抛出HTTPException
    """
    if file.content_type not in allowed_types:
        raise HTTPException(
            status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE,
            detail=f"不支持的文件类型: {file.content_type}"
        )


def is_image_file(content_type: str) -> bool:
    """
    判断文件是否为图片类型
    """
    return content_type in ALLOWED_IMAGE_TYPES


def is_video_file(content_type: str) -> bool:
    """
    判断文件是否为视频类型
    """
    return content_type in ALLOWED_VIDEO_TYPES


def generate_filename(original_filename: str) -> str:
    """
    生成唯一的文件名
    """
    file_ext = os.path.splitext(original_filename)[1]
    unique_filename = f"{uuid.uuid4().hex}{file_ext}"
    return unique_filename


async def save_file(file: UploadFile, save_path: str) -> int:
    """
    保存文件到指定路径
    返回文件大小
    """
    file_size = 0
    async with aiofiles.open(save_path, 'wb') as f:
        while chunk := await file.read(1024):
            file_size += len(chunk)
            await f.write(chunk)
    return file_size


async def resize_image(image_path: str, max_width: int = 800, max_height: int = 800):
    """
    调整图片大小
    只处理真正的图片文件，对非图片文件跳过处理
    """
    try:
        # 检查文件是否存在
        if not os.path.exists(image_path):
            print(f"图片文件不存在: {image_path}")
            return
            
        # 尝试打开图片文件
        with Image.open(image_path) as img:
            # 验证是否为有效的图片格式
            img.verify()
            
        # 重新打开图片进行处理（verify后需要重新打开）
        with Image.open(image_path) as img:
            # 如果是RGBA模式，转换为RGB
            if img.mode == 'RGBA':
                img = img.convert('RGB')
            
            # 计算新的尺寸
            width, height = img.size
            if width > max_width or height > max_height:
                img.thumbnail((max_width, max_height), Image.Resampling.LANCZOS)
                img.save(image_path, quality=85, optimize=True)
                print(f"图片已调整大小: {image_path} ({width}x{height})")
            else:
                print(f"图片尺寸符合要求，无需调整: {image_path} ({width}x{height})")
                
    except Exception as e:
        print(f"图片处理失败: {str(e)} - 文件: {image_path}")
        # 对于非图片文件，这是正常情况，不需要抛出异常


@router.post("/avatar", summary="上传头像")
async def upload_avatar(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    上传用户头像
    """
    # 验证文件
    validate_file_size(file, MAX_AVATAR_SIZE)
    validate_file_type(file, ALLOWED_IMAGE_TYPES)
    
    # 生成文件名和路径
    filename = generate_filename(file.filename)
    file_path = os.path.join(AVATAR_DIR, filename)
    
    try:
        # 保存文件
        file_size = await save_file(file, file_path)
        
        # 调整图片大小
        await resize_image(file_path, 400, 400)
        
        # 记录文件信息
        upload_record = UploadFileModel(
            user_id=current_user.id,
            original_name=file.filename,
            file_name=filename,
            file_path=file_path,
            file_size=file_size,
            file_type="avatar",
            mime_type=file.content_type,
            upload_time=datetime.now()
        )
        
        db.add(upload_record)
        
        # 更新用户头像
        avatar_url = f"/uploads/avatars/{filename}"
        current_user.avatar = avatar_url
        current_user.update_time = datetime.now()
        
        db.commit()
        
        return {
            "code": 200,
            "msg": "头像上传成功",
            "data": {
                "avatar_url": avatar_url,
                "file_id": upload_record.id
            }
        }
        
    except Exception as e:
        # 删除已上传的文件
        if os.path.exists(file_path):
            os.remove(file_path)
        
        return {
            "code": 500,
            "msg": f"文件上传失败: {str(e)}"
        }


@router.post("/file", summary="上传文件")
async def upload_file(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    上传通用文件
    """
    # print(current_user,33333333333)
    # 验证文件
    validate_file_size(file, MAX_FILE_SIZE)
    validate_file_type(file, ALLOWED_FILE_TYPES)
    
    # 生成文件名和路径
    filename = generate_filename(file.filename)
    file_path = os.path.join(FILE_DIR, filename)
    
    try:
        # 保存文件
        file_size = await save_file(file, file_path)
        
        # 如果是图片文件，调整大小
        if is_image_file(file.content_type):
            await resize_image(file_path)
        elif is_video_file(file.content_type):
            print(f"视频文件上传成功: {filename} ({file.content_type})")
        else:
            print(f"文档文件上传成功: {filename} ({file.content_type})")
        
        # 记录文件信息
        upload_record = UploadFileModel(
            user_id=current_user.id,
            original_name=file.filename,
            file_name=filename,
            file_path=file_path,
            file_size=file_size,
            file_type="file",
            mime_type=file.content_type,
            upload_time=datetime.now()
        )
        
        db.add(upload_record)
        db.commit()
        
        return {
            "code": 200,
            "msg": "文件上传成功",
            "data": {
                "file_url": f"/uploads/files/{filename}",
                "file_id": upload_record.id,
                "original_name": file.filename,
                "file_size": file_size,
                "mime_type": file.content_type
            }
        }
        
    except Exception as e:
        # 删除已上传的文件
        if os.path.exists(file_path):
            os.remove(file_path)
        
        return {
            "code": 500,
            "msg": f"文件上传失败: {str(e)}"
        }


@router.post("/files", summary="批量上传文件")
async def upload_files(
    files: List[UploadFile] = File(...),
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    批量上传文件
    """
    if len(files) > 20:
        return {
            "code": 500,
            "msg": "一次最多上传10个文件"
        }
    
    results = []
    upload_records = []
    
    for file in files:
        try:
            # 验证文件
            validate_file_size(file, MAX_FILE_SIZE)
            validate_file_type(file, ALLOWED_FILE_TYPES)
            
            # 生成文件名和路径
            filename = generate_filename(file.filename)
            file_path = os.path.join(FILE_DIR, filename)
            
            # 保存文件
            file_size = await save_file(file, file_path)
            
            # 如果是图片文件，调整大小
            if is_image_file(file.content_type):
                await resize_image(file_path)
            elif is_video_file(file.content_type):
                print(f"批量上传-视频文件: {filename} ({file.content_type})")
            else:
                print(f"批量上传-文档文件: {filename} ({file.content_type})")
            
            # 记录文件信息
            upload_record = UploadFileModel(
                user_id=current_user.id,
                original_name=file.filename,
                file_name=filename,
                file_path=file_path,
                file_size=file_size,
                file_type="file",
                mime_type=file.content_type,
                upload_time=datetime.now()
            )
            
            upload_records.append(upload_record)
            
            results.append({
                "code": 200,
                "msg": "文件上传成功",
                "success": True,
                "original_name": file.filename,
                "file_url": f"/uploads/files/{filename}",
                "file_size": file_size,
                "mime_type": file.content_type
            })
            
        except Exception as e:
            results.append({
                "code": 500,
                "msg": "文件上传失败",
                "success": False,
                "original_name": file.filename,
                "error": str(e)
            })
    
    # 批量保存记录
    if upload_records:
        db.add_all(upload_records)
        db.commit()
    
    return {
        "code": 200,
        "msg": "批量上传完成",
        "data": {
            "results": results,
            "success_count": len([r for r in results if r["success"]]),
            "total_count": len(files)
        }
    }


@router.get("/files", summary="获取用户上传的文件列表")
async def get_user_files(
    page: int = 1,
    size: int = 20,
    file_type: Optional[str] = None,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    获取当前用户上传的文件列表
    """
    query = db.query(UploadFileModel).filter(
        UploadFileModel.user_id == current_user.id,
        UploadFileModel.is_delete == False
    )
    
    if file_type:
        query = query.filter(UploadFileModel.file_type == file_type)
    
    # 分页
    total = query.count()
    files = query.order_by(UploadFileModel.upload_time.desc()).offset((page - 1) * size).limit(size).all()
    
    file_list = []
    for file in files:
        file_url = f"/uploads/{file.file_type}s/{file.file_name}" if file.file_type == "avatar" else f"/uploads/files/{file.file_name}"
        file_list.append({
            "id": file.id,
            "original_name": file.original_name,
            "file_url": file_url,
            "file_size": file.file_size,
            "file_type": file.file_type,
            "mime_type": file.mime_type,
            "upload_time": file.upload_time
        })
    
    return {
        "code": 200,
        "msg": "获取文件列表成功",
        "data": {
            "files": file_list,
            "total": total,
            "page": page,
            "size": size,
            "pages": (total + size - 1) // size
        }
    }


@router.delete("/file/{file_id}", summary="删除文件")
async def delete_file(
    file_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db)
):
    """
    删除用户上传的文件
    """
    file_record = db.query(UploadFileModel).filter(
        UploadFileModel.id == file_id,
        UploadFileModel.user_id == current_user.id,
        UploadFileModel.is_delete == False
    ).first()
    
    if not file_record:
        return {
            "code": 500,
            "msg": "文件不存在"
        }
    
    # 标记为删除
    file_record.is_delete = True
    
    # 如果是头像，清空用户头像
    if file_record.file_type == "avatar" and current_user.avatar:
        if file_record.file_name in current_user.avatar:
            current_user.avatar = None
            current_user.update_time = datetime.now()
    
    db.commit()
    
    # 删除物理文件
    try:
        if os.path.exists(file_record.file_path):
            os.remove(file_record.file_path)
    except Exception as e:
        print(f"删除物理文件失败: {str(e)}")
    
    return {
        "code": 200,
        "msg": "文件删除成功"
    }
